{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 常用Python标准库\n",
    "\n",
    "Python标准库是Python安装的一部分。 它包含各种软件包，在构建Python杰作时可能会有所帮助。 本课件列出了一些常用的包装及其主要功能。\n",
    "\n",
    "\n",
    "### 时间处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "现在时间: 2021-03-30 09:54:07.121535\n"
     ]
    }
   ],
   "source": [
    "import datetime as dt\n",
    "\n",
    "local_now = dt.datetime.now()  # 当前时间 UTC +8 东八区\n",
    "print('现在时间: {}'.format(local_now))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(local_now)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "格林威治标准时间: 2021-03-30 01:55:52.370935\n"
     ]
    }
   ],
   "source": [
    "utc_now = dt.datetime.utcnow() # UTC +0 格林威治标准时间 （GMT）\n",
    "print('格林威治标准时间: {}'.format(utc_now))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020年 12月 20日 17时 4分 37秒\n"
     ]
    }
   ],
   "source": [
    "# 输出每个时间数值\n",
    "print('{}年 {}月 {}日 {}时 {}分 {}秒'.format(local_now.year, local_now.month,\n",
    "                                             local_now.day, local_now.hour,\n",
    "                                             local_now.minute, local_now.second))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "date: 2020-12-13\n",
      "time: 10:54:18.904095\n"
     ]
    }
   ],
   "source": [
    "# 拆开日期和时间\n",
    "print('date: {}'.format(local_now.date()))\n",
    "print('time: {}'.format(local_now.time()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 字符串转为时间  `strptime()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "my_dt: 2000-01-01 10:00:00, 现在类型：<class 'datetime.datetime'>, 原来类型：<class 'str'>\n"
     ]
    }
   ],
   "source": [
    "dt_string = '2000/01/01 10:00:00' # 字符串\n",
    "my_dt = dt.datetime.strptime(dt_string, '%Y/%m/%d %H:%M:%S')\n",
    "print('my_dt: {}, 现在类型：{}, 原来类型：{}'.format(my_dt, type(my_dt), type(dt_string)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####  时间偏移`timedelta`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "明天是: 2020-12-14 10:57:55.533005\n"
     ]
    }
   ],
   "source": [
    "tomorrow = local_now + dt.timedelta(days=1) # +代表未来\n",
    "print('明天是: {}'.format(tomorrow))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "明天与今天相差 1 day, 0:36:58.782071\n",
      "相差天数: 1, 相差秒数: 2218\n",
      "相差总秒数: 88618.782071\n"
     ]
    }
   ],
   "source": [
    "delta = tomorrow - local_now              # 两个日期直接相见\n",
    "print('明天与今天相差 {}'.format(delta))   \n",
    "print('相差天数: {}, 相差秒数: {}'.format(delta.days, delta.seconds))\n",
    "print('相差总秒数: {}'.format(delta.total_seconds()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 练习1\n",
    "\n",
    "输出今天，昨天，明天日期。 格式：'%Y-%m-%d' ，函数`strftime()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "今天是2021-03-30\n",
      "今天是2021-03-30\n",
      "昨天是2021-03-29\n",
      "明天是2021-03-31\n"
     ]
    }
   ],
   "source": [
    "import datetime as dt\n",
    "today = dt.datetime.today()\n",
    "# 两种方式\n",
    "print(f'今天是{today.strftime(\"%Y-%m-%d\")}') \n",
    "print(f'今天是{today:%Y-%m-%d}')\n",
    "yesterday = today - dt.timedelta(days=1)\n",
    "print(f'昨天是{yesterday:%Y-%m-%d}')\n",
    "tomorrow = today + dt.timedelta(days=1)\n",
    "print(f'明天是{tomorrow:%Y-%m-%d}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 日志处理\n",
    "\n",
    "\n",
    "在实际应用中，日志文件十分重要，通过日志文件，我们知道程序运行的细节；\n",
    "\n",
    "同时，当程序出问题时，我们也可以通过日志快速定位问题所在。\n",
    "\n",
    "在我们写程序时，也可以借助logging模块的输出信息来调试代码。\n",
    "\n",
    "但是很多人还是在程序中使用print()函数来输出一些信息。\n",
    "\n",
    "\n",
    "#### 简单配置\n",
    "\n",
    "#### 日志级别\n",
    "\n",
    "|级别|何时使用|\n",
    "|--|--|\n",
    "|DEBUG|\t详细信息，典型地调试问题时会感兴趣。|\n",
    "|INFO|\t证明事情按预期工作。|\n",
    "|WARNING|表明发生了一些意外，或者不久的将来会发生问题（如‘磁盘满了’）。软件还是在正常工作。|\n",
    "|ERROR|\t由于更严重的问题，软件已不能执行一些功能了。|\n",
    "|CRITICAL|\t严重错误，表明软件已不能继续运行了。|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:__main__:这是Debug\n",
      "INFO:__main__:这是info\n",
      "WARNING:__main__:这是warning\n",
      "ERROR:__main__:这是error\n",
      "CRITICAL:__main__:----------这是critical-------\n"
     ]
    }
   ],
   "source": [
    "import logging\n",
    "\n",
    "# 通过下面的方式进行简单配置输出方式与日志级别\n",
    "logger = logging.getLogger(__name__)\n",
    "logging.basicConfig(level=logging.DEBUG) # level设置记录log的等级,高于这个级别才会记录,\n",
    "\n",
    "# 等级如下，越往下等级越高\n",
    "logger.debug('这是Debug')   \n",
    "logger.info('这是info')\n",
    "logger.warning('这是warning')\n",
    "logger.error('这是error')\n",
    "logger.critical('----------这是critical-------')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####  基础设置\n",
    "\n",
    "我们主要调用`basicConfig(***kwargs*)`这个函数对logging进行设置。\n",
    "\n",
    "常用的参数如下:\n",
    "\n",
    "- level：主要调整logging的级别\n",
    "- filename：输出日志的路径\n",
    "- filemode：直接写入还是追加写入\n",
    "- format：输出的格式\n",
    "\n",
    "我们通过调整format，可以输出我们想要的格式，比如：\n",
    "\n",
    "## 注意：更改logging配置重启整个页面\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2020-12-13 11:01:26,901 | __main__     | WARNING    | 我是一个警告\n",
      "2020-12-13 11:01:26,906 | __main__     | ERROR      | 这里有个错误\n"
     ]
    }
   ],
   "source": [
    "import logging\n",
    "\n",
    "# 使用以下方式reload可以避免重启页面，只限在jupyter使用\n",
    "from importlib import reload\n",
    "reload(logging)\n",
    "\n",
    "my_format = '%(asctime)s | %(name)-12s | %(levelname)-10s | %(message)s'\n",
    "logging.basicConfig(format=my_format)\n",
    "\n",
    "logger = logging.getLogger(__name__)\n",
    "\n",
    "logger.warning('我是一个警告')\n",
    "logger.error('这里有个错误')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 随机函数 `random`\n",
    "\n",
    "random() 方法返回随机生成的一个浮点数，它在[0,1)范围内。\n",
    "\n",
    "randint() 方法返回随机生成的一个整数，范围由用户指定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "随机整数1-100: 71\n",
      "随机浮点数 0-1: 0.1604382114688041\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "\n",
    "rand_int = random.randint(1, 100)\n",
    "print('随机整数1-100: {}'.format(rand_int))\n",
    "\n",
    "rand = random.random()\n",
    "print('随机浮点数 0-1: {}'.format(rand))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 更多用法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "0.5518522045209643\n",
      "1.2232953637812358\n",
      "o\n",
      "57\n"
     ]
    }
   ],
   "source": [
    "print( random.randint(1,10) )        # 产生 1 到 10 的一个整数型随机数  \n",
    "print( random.random() )             # 产生 0 到 1 之间的随机浮点数\n",
    "print( random.uniform(1.1,5.4) )     # 产生  1.1 到 5.4 之间的随机浮点数，区间可以不是整数\n",
    "print( random.choice('tomorrow') )   # 从序列中随机选取一个元素\n",
    "print( random.randrange(1,100,2) )   # 生成从1到100的间隔为2的随机整数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 计算机不是真正的随机\n",
    "\n",
    "我们可以对比以下两个例子，第一个例子每次运行随机都是不一样的，第二种我们可以固定一直随机方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.05498669985725413\n",
      "0.9965308571255679\n",
      "0.23594056745868885\n",
      "0.3533274679516817\n",
      "0.5264279344269548\n",
      "0.13026427863581802\n",
      "0.22622814754239584\n",
      "0.34902754012103265\n",
      "0.1329035445710124\n",
      "0.8171283991989615\n"
     ]
    }
   ],
   "source": [
    "for _ in range(10):\n",
    "    print(random.random())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.23604808973743452\n",
      "0.1031660342307158\n",
      "0.396058242610681\n",
      "0.15497227080241027\n",
      "0.06651509567958991\n",
      "0.40159101448507484\n",
      "0.9179550430877189\n",
      "0.8004523514958085\n",
      "0.7651626025054384\n",
      "0.22192817569031764\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "\n",
    "random.seed(4)  # 创建种子，也就是限定随机因子，因此每次随机的数字顺序都是一样\n",
    "\n",
    "for _ in range(10):\n",
    "    print(random.random())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 练习3\n",
    "\n",
    "随机生成10道100以内的数学运算题目，格式如下：5 + 2 = ？，运算符号有：+，/，-，*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第1题：5 + 10 = ?\n",
      "第2题：59 * 80 = ?\n",
      "第3题：66 / 68 = ?\n",
      "第4题：89 - 43 = ?\n",
      "第5题：86 + 25 = ?\n",
      "第6题：52 / 25 = ?\n",
      "第7题：35 * 23 = ?\n",
      "第8题：55 * 95 = ?\n",
      "第9题：81 - 71 = ?\n",
      "第10题：41 + 12 = ?\n"
     ]
    }
   ],
   "source": [
    "from random import randint, choice, seed\n",
    "\n",
    "#seed(4)  有创建种子每次出来的题目是一样的\n",
    "for i in range(10):\n",
    "    a = randint(0, 100)\n",
    "    b = randint(0, 100)\n",
    "    operate = choice('+-*/')\n",
    "    print(f\"第{i+1}题：{a} {operate} {b} = ?\")\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
